package com.yowasa.xiuxian.engine.message.interact;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yowasa.xiuxian.annoations.CMD;
import com.yowasa.xiuxian.engine.CommonEngine;
import com.yowasa.xiuxian.engine.item.ItemInterface;
import com.yowasa.xiuxian.engine.message.CmdMessageHandler;
import com.yowasa.xiuxian.entity.bo.item.ItemAttr;
import com.yowasa.xiuxian.entity.bo.item.UserItemBo;
import com.yowasa.xiuxian.entity.bo.user.UserBO;
import com.yowasa.xiuxian.entity.enums.CmdScopeEnum;
import com.yowasa.xiuxian.entity.enums.MapEnum;
import com.yowasa.xiuxian.entity.enums.QualityEnum;
import com.yowasa.xiuxian.entity.mys.SendMessage;
import com.yowasa.xiuxian.entity.po.XiuxianTransactPO;
import com.yowasa.xiuxian.entity.po.XiuxianUserEmail;
import com.yowasa.xiuxian.exception.HandlerException;
import com.yowasa.xiuxian.mapper.XiuxianTransactMapper;
import com.yowasa.xiuxian.service.helper.EmailHelper;
import com.yowasa.xiuxian.service.helper.ItemHelper;
import com.yowasa.xiuxian.service.helper.MessageHelper;
import com.yowasa.xiuxian.service.helper.UserHelper;
import com.yowasa.xiuxian.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@CMD(name = "/拍卖行", scope = CmdScopeEnum.ALL)
public class TransactPlayerHandler extends CmdMessageHandler {

    @Autowired
    private UserHelper userHelper;
    @Autowired
    private MessageHelper messageHelper;
    @Autowired
    private ItemHelper itemHelper;
    @Autowired
    private XiuxianTransactMapper xiuxianTransactMapper;
    @Autowired
    private EmailHelper emailHelper;

    public static final Logger logger = LoggerFactory.getLogger(MessageHelper.class);

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public void execute(SendMessage message) {
        UserBO userBO = userHelper.checkOpUser(message);
        MapEnum map = MapEnum.getById(userBO.getLocal());
        if (!userBO.getUserConfig().getStudiedSpecialEffect().contains("仙灵店铺") && map.getType() != 2) {
            throw new HandlerException("只有城市中有拍卖行");
        }
        List<String> params = getAllParam(message);//获取名称
        if (StringUtils.isEmpty(params.get(0))) {
            messageHelper.replyMys(message, "可以在后面追加 我的 查询 出价 上架 购买 求购 出售 下架 等二级指令进行后续操作\n 购买是一口价直接购买，出价是参与拍卖,一口价默认为上架价格的1.5倍\n\n拍卖行每日凌晨1点结算，物品与摩拉会发入邮箱请注意领取");
            return;
        }
        if ("我的".equals(params.get(0))) {
            List<XiuxianTransactPO> xiuxianTransactPOS = xiuxianTransactMapper.selectList(new LambdaQueryWrapper<XiuxianTransactPO>()
                    .eq(XiuxianTransactPO::getAccountId, userBO.getId())
                    .ne(XiuxianTransactPO::getStatus, 0)
                    .gt(XiuxianTransactPO::getItemNum, 0)
            );
            if (CollectionUtils.isEmpty(xiuxianTransactPOS)) {
                messageHelper.replyMys(message, "尚未上架过物品");
            }
            String msg = itemHelper.buildBatchTransactMsgT(xiuxianTransactPOS);
            messageHelper.replyMys(message, msg);
            return;
        }
        if ("查询".equals(params.get(0))) {
            if(params.size() < 2){
                throw new HandlerException("请输入要查询的页码或名称");
            }
            String itemName;
            List<XiuxianTransactPO> buy = new ArrayList<>();
            if (NumberUtil.isInteger(params.get(1))) {
                LambdaQueryWrapper<XiuxianTransactPO> eq = new LambdaQueryWrapper<XiuxianTransactPO>()
                        .eq(XiuxianTransactPO::getStatus, 1);
                int i = Integer.parseInt(params.get(1));
                Page<XiuxianTransactPO> page = new Page<>(i,20);
                Page<XiuxianTransactPO> pageRecords = xiuxianTransactMapper.selectPage(page, eq);
                buy = pageRecords.getRecords();
            } else {
                itemName = params.get(1);
                buy = xiuxianTransactMapper.selectList(new LambdaQueryWrapper<XiuxianTransactPO>()
                        .eq(XiuxianTransactPO::getItemName, itemName)
                        .ne(XiuxianTransactPO::getStatus, 0)
                        .orderByAsc(XiuxianTransactPO::getStatus)
                        .orderByDesc(XiuxianTransactPO::getItemPrice)
                );
            }

            StringBuffer msg = new StringBuffer().append("[拍卖行]\n");

            //【物品】*数量，当前出价，一口价
            msg.append("id【物品】*数量，当前出价，一口价\n");
            msg.append(createMsg(buy));
            messageHelper.replyMys(message, msg.toString());
            return;
        }
        if ("上架".equals(params.get(0))) {
            if (params.size() < 3) {
                throw new HandlerException("请在上架后输入 物品名 总价 数量 不输入数量默认为1\n上架的是装备，请将数量替换为品质\n装备一次仅能上架一件");
            }
            String itemName = params.get(1);
            int price = StrUtil.checkAndConvert2Int(params.get(2), "价格");
            int num = 1;

            ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(itemName);
            if(itemInterface == null){
                throw new HandlerException("不存在这样的物品");
            }
            UserItemBo myItem;
            if(itemInterface.getType().getId() == 3){
                String quality = params.get(3);
                QualityEnum qualityEnum = QualityEnum.getByName(quality);
                myItem = itemHelper.getMyEqip(userBO.getId(),itemName,qualityEnum.getId());
            }else {
                if (params.size() >= 4) {
                    num = StrUtil.checkAndConvert2Int(params.get(3), "数量");
                }
                myItem = itemHelper.getMyItem(userBO.getId(), itemName);
            }

            if (myItem == null) {
                throw new HandlerException("你身上未持有该道具:" + itemName);
            }
            if (myItem.getItemNum() < num) {
                throw new HandlerException(MessageFormat.format("你身上道具[{0}]持有数量为{1},不足{2}", itemName, myItem.getItemNum(), num));
            }
            //身上道具移除
            itemHelper.dropItem(myItem, num);
            //拍卖行增加一条数据
            XiuxianTransactPO xiuxianTransact = new XiuxianTransactPO();
            xiuxianTransact.setStatus(1);
            xiuxianTransact.setItemNum(num);
            xiuxianTransact.setItemName(itemName);
            xiuxianTransact.setAccountId(userBO.getId());
            xiuxianTransact.setItemPrice(price);
            xiuxianTransact.setItemType(myItem.getItemType());
            xiuxianTransact.setItemDesc(myItem.getItemDesc());
            xiuxianTransact.setItemAttr(myItem.getItemAttr());
            xiuxianTransact.setNowPrice(price / 2);
            xiuxianTransact.setNowAccount(0L);
            xiuxianTransact.setCreateTime(new Date());
            xiuxianTransactMapper.insert(xiuxianTransact);
            messageHelper.replyMys(message, "上架成功");
            return;
        }

        if ("下架".equals(params.get(0))) {
            if (params.size() < 2) {
                throw new HandlerException("请输入要下架的编号");
            }
            String id = params.get(1);
            Integer num = StrUtil.checkAndConvert2Int(id, "编号");

            XiuxianTransactPO transactPO = xiuxianTransactMapper.selectById(num);
            if (ObjectUtil.isNull(transactPO) || transactPO.getStatus() != 2) {
                throw new HandlerException("该求购不存在或已经达成！");
            }

            if(!transactPO.getAccountId().equals(userBO.getId())){
                throw new HandlerException("不是你发布的求购！");
            }
            transactPO.setStatus(0);
            xiuxianTransactMapper.updateById(transactPO);
            userBO.getUserConfig().setGold(userBO.getUserConfig().getGold() + transactPO.getItemPrice());
            userHelper.saveUserInfo(userBO);
            messageHelper.replyMys(message, "下架成功");
            return;
        }
        if ("求购".equals(params.get(0))) {
            // 求购 物品 数量 总价
            if (params.size() < 3) {
                throw new HandlerException("请在求购后输入 物品名 总价 数量 不输入数量默认为1\n求购的是装备，请将数量替换为品质\n装备一次仅能求购一件\n\n或输入查询+页码，进行所有求购条目的查询");
            }
            String itemName = params.get(1);
            if(itemName.equals("查询")){
                LambdaQueryWrapper<XiuxianTransactPO> eq = new LambdaQueryWrapper<XiuxianTransactPO>()
                        .eq(XiuxianTransactPO::getStatus, 2);
                int i = 1;
                try {
                    i = Integer.parseInt(params.get(2));
                }catch (Exception e){
                    i = 1;
                }
                Page<XiuxianTransactPO> page = new Page<>(i,10);
                Page<XiuxianTransactPO> pageRecords = xiuxianTransactMapper.selectPage(page, eq);
                List<XiuxianTransactPO> buy = pageRecords.getRecords();
                messageHelper.replyMys(message,createMsg(buy));
            }else {
                int price = StrUtil.checkAndConvert2Int(params.get(2), "价格");
                int num = 1;
                QualityEnum qualityEnum = QualityEnum.LIANG;
                ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(itemName);
                if(itemInterface == null){
                    throw new HandlerException("不存在这样的物品");
                }
                if(itemInterface.getType().getId() == 3){
                    String quality = params.get(3);
                    qualityEnum = QualityEnum.getByName(quality);
                }else {
                    if (params.size() >= 4) {
                        num = StrUtil.checkAndConvert2Int(params.get(3), "数量");
                    }
                }
                if(userBO.getUserConfig().getGold() < price){
                    throw new HandlerException("你身上没有足够的摩拉");
                }else {
                    userBO.getUserConfig().setGold(userBO.getUserConfig().getGold() - price);
                    userHelper.saveUserInfo(userBO);
                }
                //拍卖行增加一条数据
                XiuxianTransactPO xiuxianTransact = new XiuxianTransactPO();
                xiuxianTransact.setStatus(2);
                xiuxianTransact.setItemNum(num);
                xiuxianTransact.setItemName(itemName);
                xiuxianTransact.setAccountId(userBO.getId());
                xiuxianTransact.setItemPrice(price);
                xiuxianTransact.setItemType(itemInterface.getType().getId());
                xiuxianTransact.setItemDesc(itemInterface.desc());
                xiuxianTransact.setItemAttr(itemInterface.attr(qualityEnum));
                xiuxianTransact.setNowPrice(price);
                xiuxianTransact.setNowAccount(0L);
                xiuxianTransact.setCreateTime(new Date());
                xiuxianTransactMapper.insert(xiuxianTransact);
                messageHelper.replyMys(message, "发布求购成功");

            }
        }
        if ("出售".equals(params.get(0))) {
            if (params.size() < 2) {
                throw new HandlerException("请输入要出售的编号");
            }
            String id = params.get(1);
            Integer num = StrUtil.checkAndConvert2Int(id, "编号");

            XiuxianTransactPO transactPO = xiuxianTransactMapper.selectById(num);
            if (ObjectUtil.isNull(transactPO) || transactPO.getStatus() != 2) {
                throw new HandlerException("该求购不存在或已经达成！");
            }

            ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(transactPO.getItemName());
            UserItemBo myItem;
            if(itemInterface.getType().getId() == 3){
                ItemAttr itemAttr = JSONUtil.toBean(transactPO.getItemAttr(), ItemAttr.class);
                myItem = itemHelper.getMyEqip(userBO.getId(),transactPO.getItemName(),itemAttr.getQuality());
            }else {
                myItem = itemHelper.getMyItem(userBO.getId(), transactPO.getItemName());
            }

            if (myItem == null) {
                throw new HandlerException("你身上未持有该道具:" + transactPO.getItemName());
            }
            if (myItem.getItemNum() < transactPO.getItemNum()) {
                throw new HandlerException(MessageFormat.format("你身上道具[{0}]持有数量为{1},不足{2}", transactPO.getItemName(), myItem.getItemNum(), transactPO.getItemNum()));
            }
            //身上道具移除
            itemHelper.dropItem(myItem, transactPO.getItemNum());

            //求购人获得物品，邮箱
            XiuxianUserEmail email = new XiuxianUserEmail(transactPO.getAccountId());
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type",itemInterface.getType().getId());
            jsonObject.put("name",itemInterface.getName());
            jsonObject.put("num", transactPO.getItemNum());
            if(itemInterface.getType().getId() == 3){
                ItemAttr itemAttr = JSONUtil.toBean(transactPO.getItemAttr(), ItemAttr.class);
                jsonObject.put("quality",itemAttr.getQuality());
            }else {
                jsonObject.put("quality",2);
            }

            email.setExtra(jsonObject.toString());
            email.setTitle("拍卖行求购");
            email.setMsg("你在拍卖行发布的求购[" + transactPO.getItemName() + "]被人完成");
            emailHelper.insert(email);

            //出售人拿钱
            userBO.getUserConfig().setGold(userBO.getUserConfig().getGold() + transactPO.getItemPrice());
            userHelper.saveUserInfo(userBO);
            //拍卖行状态修改
            transactPO.setNowAccount(userBO.getId());
            transactPO.setStatus(0);
            transactPO.setUpdateTime(new Date());
            xiuxianTransactMapper.updateById(transactPO);
            messageHelper.replyMys(message, "出售成功！");
        }
        //一口价购买
        if ("购买".equals(params.get(0))) {
            if (params.size() < 2) {
                throw new HandlerException("请输入要购买的编号");
            }
            String id = params.get(1);
            Integer num = StrUtil.checkAndConvert2Int(id, "编号");

            XiuxianTransactPO transactPO = xiuxianTransactMapper.selectOne(new LambdaQueryWrapper<XiuxianTransactPO>().eq(XiuxianTransactPO::getId,num).last(" for update"));
            if (ObjectUtil.isNull(transactPO) || transactPO.getStatus() != 1) {
                throw new HandlerException("该物品不存在或已经售出！");
            }
            //价格
            int cost = (int) Math.round(transactPO.getItemPrice() * 1.5);
            if (userBO.getUserConfig().getGold() < cost) {
                throw new HandlerException("你身上的摩拉不足，需要:" + cost);
            }
            String itemName = transactPO.getItemName();
            ItemInterface itemInterface = CommonEngine.ITEM_MAP.get(itemName);
            // 扣钱
            userBO.getUserConfig().setGold((userBO.getUserConfig().getGold() - cost));
            //加物品
            if (itemInterface.getType().getId() == 3) {
                ItemAttr itemAttr = JSONUtil.toBean(transactPO.getItemAttr(), ItemAttr.class);
                itemHelper.addEquip(userBO, itemInterface, transactPO.getItemNum(), itemAttr.getQuality());
            } else {
                itemHelper.addItem(userBO, itemInterface, transactPO.getItemNum());
            }
            //拍卖行下架
            if (transactPO.getNowAccount() != 0L) {
                //退还上一个出价的人
                XiuxianUserEmail email = new XiuxianUserEmail(transactPO.getNowAccount());
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("type",0);
                jsonObject.put("name","摩拉");
                jsonObject.put("num",transactPO.getNowPrice());
                jsonObject.put("quality",2);
                email.setExtra(jsonObject.toString());
                email.setTitle("拍卖行出价退还");
                email.setMsg("你在拍卖行的出价购买的[" + transactPO.getItemName() + "]被人超过，已退还摩拉" + transactPO.getNowPrice());
                emailHelper.insert(email);
            }
            //寄售人获得钱

            XiuxianUserEmail email = new XiuxianUserEmail(transactPO.getAccountId());
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type",0);
            jsonObject.put("name","摩拉");
            jsonObject.put("num",cost);
            jsonObject.put("quality",2);
            email.setExtra(jsonObject.toString());
            email.setTitle("拍卖行售出");
            email.setMsg("你在拍卖行寄售的[" + transactPO.getItemName() + "]被人购买，获得摩拉" + cost);
            emailHelper.insert(email);
            userHelper.saveUserInfo(userBO);
            transactPO.setNowAccount(userBO.getId());
            transactPO.setStatus(0);
            transactPO.setUpdateTime(new Date());
            xiuxianTransactMapper.updateById(transactPO);
            messageHelper.replyMys(message, "购买成功");
            return;
        }
        if ("出价".equals(params.get(0))) {
            if (params.size() < 3) {
                throw new HandlerException("请在出价后输入 编号 价格");
            }
            String id = params.get(1);
            Integer num = StrUtil.checkAndConvert2Int(id, "编号");
            Integer price = StrUtil.checkAndConvert2Int(params.get(2), "价格");

            XiuxianTransactPO transactPO = xiuxianTransactMapper.selectById(num);
//            logger.info("用户{}出价，物品为{}\n编号为：{}，价格为：{}",userBO.getId(),transactPO,num,price);
            if (ObjectUtil.isNull(transactPO) || transactPO.getStatus() != 1) {
                throw new HandlerException("该物品不存在或已经售出！");
            }
            if (userBO.getUserConfig().getGold() < price) {
                throw new HandlerException("你身上的摩拉不足，需要:" + price);
            }

            if (price <= transactPO.getNowPrice()) {
                throw new HandlerException("出价需要比当前价格高！");
            } else {
                //上一个出价的人拿回钱
                if(transactPO.getNowAccount() != 0 ) {
                    XiuxianUserEmail email = new XiuxianUserEmail(transactPO.getNowAccount());
                    //                //"["type":1,"name":"金疮药","num":10,"quality":2]"
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("type",0);
                    jsonObject.put("name","摩拉");
                    jsonObject.put("num",transactPO.getNowPrice());
                    jsonObject.put("quality",2);
                    email.setExtra(jsonObject.toString());
                    email.setTitle("拍卖行出价退还");
                    email.setMsg("你在拍卖行的出价购买的[" + transactPO.getItemName() + "]被人超过，已退还摩拉" + transactPO.getNowPrice());
                    emailHelper.insert(email);
                }
            }

            // 扣钱
            userBO.getUserConfig().setGold((userBO.getUserConfig().getGold() - price));
            //修改出价人
            transactPO.setNowAccount(userBO.getId());
            transactPO.setNowPrice(price);
            transactPO.setUpdateTime(new Date());
            xiuxianTransactMapper.updateById(transactPO);
            userHelper.saveUserInfo(userBO);
            messageHelper.replyMys(message, "出价成功，当前出价为" + price);
            return;
        }
    }

    private String createMsg(List<XiuxianTransactPO> buy){
        StringBuffer msg = new StringBuffer();
        for (XiuxianTransactPO po : buy) {
            if(po.getStatus() == 1){
                msg.append("[拍卖] ");
            }else {
                msg.append("[求购] ");
            }
            if(po.getItemType() == 3){
                ItemAttr itemAttr = JSONUtil.toBean(po.getItemAttr(), ItemAttr.class);
                QualityEnum byId = QualityEnum.getById(itemAttr.getQuality());
                msg.append(po.getId() + "  [" +byId.getName()+"-" +po.getItemName() + "]*" + po.getItemNum() + "   " + po.getNowPrice() + "    " + po.getItemPrice() * 1.5 + "\n");
            }else {
                msg.append(po.getId() + "  [" + po.getItemName() + "]*" + po.getItemNum() + "   " + po.getNowPrice() + "    " + po.getItemPrice() * 1.5 + "\n");
            }
        }
        return msg.toString();
    }

    public String desc(){
        return new StringBuffer().append("拍卖行为玩家间交易使用\n")
                .append("使用 /拍卖行 可获取一些提示\n")
                .append("如果是购买自己上架的物品，会拿回物品，但是扣除摩拉")
                .toString();

    }
}
